/*
 *  Copyright (C) 2004 Cidero, Inc.
 *
 *  Permission is hereby granted to any person obtaining a copy of 
 *  this software to use, copy, modify, merge, publish, and distribute
 *  the software for any non-commercial purpose, subject to the
 *  following conditions:
 *  
 *  The above copyright notice and this permission notice shall be included
 *  in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
 *  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
 *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY IN CONNECTION WITH THE SOFTWARE.
 * 
 *  File: $RCSfile: PrismiqDeviceMonitor.java,v $
 *
 */

package com.cidero.bridge.prismiq;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.util.logging.Logger;

import com.cidero.bridge.DeviceMonitorListener;

/**
 * Class <code>PrismiqDeviceMonitor</code> runs as a separate 
 * thread that monitors port 3650 for incoming UDP packets and 
 * checks to see if they contain the magic 'PRISMIQ' string. If so,
 * a callback is invoked to update the device manager
 *
 */
public class PrismiqDeviceMonitor implements Runnable
{
  private static Logger logger = 
    Logger.getLogger("com.cidero.bridge.prismiq");

  DeviceMonitorListener devMonListener;
  int                   port;

  public PrismiqDeviceMonitor( DeviceMonitorListener devMonListener,
                               int port )
  {
    this.devMonListener = devMonListener;
    this.port = port;
  }
  
  private Thread monitorThread = null;  // for clean shutdown via stop()
  
  public void run()
  {
    logger.info("PrismiqMonitorThread: Running...");

    Thread thisThread = Thread.currentThread();
    
    byte[] buf = new byte[8192];
    DatagramSocket ds;

    try 
    {
      ds = new DatagramSocket( port );  // default: 3650
      ds.setBroadcast( true );
    }
    catch( SocketException e )
    {
      logger.warning("PrismiqDeviceMonitor: Error: " + e );
      return;
    }
    
    DatagramPacket recvPacket = new DatagramPacket( buf, buf.length );

    while( monitorThread == thisThread )
    {
      //
      // Read packets forever
      //
      try 
      {
        ds.receive( recvPacket );

        //        logger.finest("Got UDP packet, length = " 
        //                    + recvPacket.getLength() 
        //                    + " IPAddress = " + recvPacket.getAddress() );

        // For some reason, getAddress() can return address with a leading
        // '/'. Strip it off if present
        String ipAddr = recvPacket.getAddress().getHostAddress();

        //        int index = ipAddr.lastIndexOf("/");
        
        //        if( index >= 0 )
        //          ipAddr = ipAddr.substring( index );
        
        devMonListener.heartbeatPacketReceived( ipAddr );

      }
      catch( Exception e )
      {
        logger.warning("PrismiqDeviceMonitor: Error: " + e );
        return;
      }
      
    }
    
    logger.info("PrismiqDeviceMonitor: Shutting down...");

  }

  public void start()
  {
    monitorThread = new Thread( this );
    monitorThread.start();  // Invokes run()
  }
  
  public void stop()
  {
    monitorThread = null;
  }
  
  
}
